/*************************************************************************
    > File Name: code.c
    > Author: ma6174
    > Mail: ma6174@163.com 
    > Created Time: Sat 01 Mar 2025 12:04:23 PM CST
 ************************************************************************/
//waitpid的调用方法，WIFEXITED和WEXITSTATUS的使用：用来检查子进程退出状态的宏。
//WIFEXITED返回非零，子进程正常退出，返回零，则子进程退出错误。
//WEXITSTATUS宏来获取子进程的退出码
//非阻塞等待示例的代码
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include"task.h"

typedef void(*func_t)();            //函数指针

#define N 3
func_t task[N] = {NULL}; 

void LoadTask()
{
	task[0] = PrintLog;        //加载信息
	task[1] = Download;         //信息下载
	task[2] = MysqlDataSync;    //数据同步
}

void HandlerTask()
{
	for(int i =0;i<N;i++)
	{
		task[i]();             //回调函数
	}
}

//father process
void DoOtherThink()
{
	HandlerTask();         //父进程在非阻塞等待时，去调用其他需要处理的任务
}

void ChildRun()            //调用子进程
{
	int cnt = 5;
	while(cnt)
	{
		printf("I am child process, pid: %d, ppid: %d,cnt: %d\n",getpid(),getppid(),cnt);
		sleep(1);
		cnt--;
	}
}

int main()
{
	printf("I am father process, pid: %d, ppid: %d\n",getpid(),getppid());

	pid_t id = fork();     //创建子进程
	if(id ==0)
	{
		//运行子进程
		ChildRun();
		printf("child quit...\n");       //调用完子进程，显示一下子进程退出信息
		exit(123);                       //程序直接在这里退出，退出码123
	}
	LoadTask();                          //父进程等待的时候先把其他任务加载
	//这里就是父进程的等待信息
	while(1)
	{	
		int status = 0;
		pid_t rid = waitpid(id,&status,WNOHANG);   
		if(rid ==0)
		{
			usleep(50000);
			printf("child process running...，father check next time!\n");
			DoOtherThink();              //父进程去作其他事情，父进程非阻塞等待
		}
		else if(rid>0)
		{
			if(WIFEXITED(status))
			{
				printf("child quit success, child exit code: %d\n",WEXITSTATUS(status));
			}
			else
			{
				printf("child quit unnormal!\n");
			}
			break;
		}
		else
		{
			printf("waitpid failed!\n");
			break;
		}
	}
}
